# -*- coding: utf-8 -*-
import uiautomator2 as u2
import cv2
from matplotlib import pyplot as plt
import np
import threading
import re
import random
import time
import pytesseract
import shutil
from PIL import Image
import os
import hashlib

pytesseract.pytesseract.tesseract_cmd = r'C:\\Program Files\\Tesseract-OCR\\tesseract.exe'

threshold = 0.8

def point(res,method,img,template):
    h, w = template.shape[:2]
    img2 = img.copy()

    res = cv2.matchTemplate(img, template, method)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

    # 如果是平方差匹配TM_SQDIFF或归一化平方差匹配TM_SQDIFF_NORMED，取最小值
    if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
        top_left = min_loc
    else:
        top_left = max_loc
    bottom_right = (top_left[0] + w, top_left[1] + h)

    # 画矩形
    cv2.rectangle(img2, top_left, bottom_right,(0,255,255), 2)

    plt.subplot(121), plt.imshow(res, cmap='gray')
    plt.xticks([]), plt.yticks([])  # 隐藏坐标轴
    plt.subplot(122), plt.imshow(img2, cmap='gray')
    plt.xticks([]), plt.yticks([])
    plt.show()

def match(new_width,image,template,show=0):

    #print('shape====',image.shape[1])
    ratio = new_width / image.shape[1]
    #print('ratio====',ratio)

    # 计算纵横比例
    ratio = new_width / image.shape[1]
    new_height = int(image.shape[0] * ratio)

    # 调整图像大小
    resized_image = cv2.resize(image, (new_width, new_height))

    #img = cv2.imread(path+'20200401213027725.jpg', 0)
    #template = cv2.imread(path+'aaaaaaa.jpg', 0)

    img=resized_image

    method = eval("cv2.TM_CCOEFF_NORMED")
    # 匹配方法的真值
    res = cv2.matchTemplate(img, template, method)

    loc = np.where(res >= threshold)

    if(len(loc[0])>0):
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
        if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
            top_left = min_loc
        else:
            top_left = max_loc
        h, w = template.shape[:2]
        #print("find img ",top_left[0]+h/2,top_left[1]+w/2)

        if(show==1):
            t = threading.Thread(point(res,method,img,template))
            t.start()

        return (top_left[0])/ratio+(w/2)/ratio,(top_left[1])/ratio+(h/2)/ratio
    else:
        return None,None

def match2(d,path,new_width,image,template,show=0):

    #print('shape====',image.shape[1])
    ratio = new_width / image.shape[1]
    #print('ratio====',ratio)

    # 计算纵横比例
    ratio = new_width / image.shape[1]
    new_height = int(image.shape[0] * ratio)

    # 调整图像大小
    resized_image = cv2.resize(image, (new_width, new_height))

    #img = cv2.imread(path+'20200401213027725.jpg', 0)
    #template = cv2.imread(path+'aaaaaaa.jpg', 0)

    img=resized_image

    method = eval("cv2.TM_CCOEFF_NORMED")
    # 匹配方法的真值
    res = cv2.matchTemplate(img, template, method)

    loc = np.where(res >= threshold)

    if(len(loc[0])>0):
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
        if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
            top_left = min_loc
        else:
            top_left = max_loc
        h, w = template.shape[:2]
        #print("find img ",top_left[0]+h/2,top_left[1]+w/2)
        bottom_right = (top_left[0] + w, top_left[1] + h)

        screenshot = d.screenshot(format='opencv')
        matched_region = screenshot[top_left[1]:bottom_right[1], top_left[0]:bottom_right[0]]
        timg = cv2.imread(path)

        if(show==1):
            plt.subplot(121), plt.imshow(timg, cmap='gray')
            plt.xticks([]), plt.yticks([])  # 隐藏坐标轴
            plt.subplot(122), plt.imshow(matched_region, cmap='gray')
            plt.xticks([]), plt.yticks([])
            plt.show()

        gray_img1 = cv2.cvtColor(matched_region, cv2.COLOR_BGR2GRAY)
        gray_img2 = cv2.cvtColor(timg, cv2.COLOR_BGR2GRAY)

        # 计算直方图
        hist_img1 = cv2.calcHist([gray_img1], [0], None, [256], [0, 256])
        hist_img2 = cv2.calcHist([gray_img2], [0], None, [256], [0, 256])

        similarity = cv2.compareHist(hist_img1, hist_img2, cv2.HISTCMP_BHATTACHARYYA)

        print(f"Similarity between image1 and image2: {similarity:.5f}")

        if(similarity<0.2):
            return (top_left[0])/ratio+(w/2)/ratio,(top_left[1])/ratio+(h/2)/ratio
        else:
            return None,None
    else:
        return None,None


def DrawRectWithText(screenshot, rect, text='aaa'):
    h, w = screenshot.shape[:2]

    x = int(w*rect[0])   # 起始 x 坐标
    y = int(h*rect[1])  # 起始 y 坐标
    width = int(w*rect[2])  # 感兴趣区域的宽度
    height = int(h*rect[3])  # 感兴趣区域的高度
    return x,y,width,height

def getqd(d,arr,n=1):
    for i in range(n):
        for a in arr:
            screenshot = d.screenshot(format='opencv')
            img = cv2.cvtColor(screenshot, cv2.COLOR_BGR2GRAY)
            template = cv2.imread('D:\\image\\'+a, 0)
            h,w=img.shape
            x,y=match(w,img,template,0)
            if(x!=None):
                return x,y
        time.sleep(1)
    return None,None


def number(image,rect,device):
    x,y,w,h=DrawRectWithText(image,rect)
    print(x,y,w,h)
    # 切片裁剪图像
    cropped_image = image[y:y+h, x:x+w]
    M_Img =Picture_Synthesis2(cropped_image)
    M_Img.save('D:\\image2\\'+device+'-eeeeeeeeeee.png')
    cropped_image=cv2.imread('D:\\image2\\'+device+'-eeeeeeeeeee.png', cv2.COLOR_BGR2GRAY)
    #cv2.imwrite('D:\\image2\\'+'-nnnnnnnnnnnnnnn.png', image, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])
    # 显示原始图像和提高分辨率后的图像
    #cv2.imshow('Original Image', cropped_image)
    #cv2.waitKey(0)

    # 转换为灰度图像
    gray_image = cv2.cvtColor(cropped_image, cv2.COLOR_BGR2GRAY)

    # 应用高斯模糊来进行抗锯齿处理
    blurred_image = cv2.GaussianBlur(cropped_image, (5, 5), 0)

    # 图像增强（锐化）来提高清晰度
    kernel = np.array([[-1, -1, -1], [-1, 9, -1], [-1, -1, -1]])  # 定义锐化核
    sharpened_image = cv2.filter2D(blurred_image, -1, kernel)

    #cv2.imwrite('D:\\image\\'+'-ffffffffffff.png', sharpened_image, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])

    custom_config = r'--oem 3 --psm 6 outputbase digits'

    # 执行光学字符识别
    text = pytesseract.image_to_string(sharpened_image,config=custom_config)

    return text

def Picture_Synthesis(son_img,serial,
                      coordinate=None):
    """
    :param mother_img: 母图
    :param son_img: 子图
    :param save_img: 保存图片名
    :param coordinate: 子图在母图的坐标
    :return:
    """

    S_Img = Image.open(son_img)

    height,width = S_Img.size
    print('width=',width,'  height=',height)
    width = width+200
    height = height+200
    mother_img= np.ones((width, height, 3), dtype=np.uint8)

    mother_img[:, :, 0] = 255  # 蓝色通道
    mother_img[:, :, 1] = 122    # 绿色通道
    mother_img[:, :, 2] = 0    # 红色通道

    cv2.imwrite('D:\\image2\\wwwwwwwww.png', mother_img, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])

    #将图片赋值,方便后面的代码调用
    M_Img = Image.open('D:\\image2\\wwwwwwwww.png')

    factor = 1#子图缩小的倍数1代表不变，2就代表原来的一半

    #给图片指定色彩显示格式
    M_Img = M_Img.convert("RGBA")  # CMYK/RGBA 转换颜色格式（CMYK用于打印机的色彩，RGBA用于显示器的色彩）

    # 获取图片的尺寸
    M_Img_w, M_Img_h = M_Img.size  # 获取被放图片的大小（母图）
    #print("母图尺寸：",M_Img.size)
    S_Img_w, S_Img_h = S_Img.size  # 获取小图的大小（子图）
    #print("子图尺寸：",S_Img.size)

    size_w = int(S_Img_w / factor)
    size_h = int(S_Img_h / factor)

    # 防止子图尺寸大于母图
    if S_Img_w > size_w:
        S_Img_w = size_w
    if S_Img_h > size_h:
        S_Img_h = size_h

    # # 重新设置子图的尺寸
    # icon = S_Img.resize((S_Img_w, S_Img_h), Image.ANTIALIAS)
    icon = S_Img.resize((S_Img_w, S_Img_h), Image.Resampling.LANCZOS)
    w = int((M_Img_w - S_Img_w) / 2)
    h = int((M_Img_h - S_Img_h) / 2)

    try:
        if coordinate==None or coordinate=="":
            coordinate=(w, h)
            # 粘贴子图到母图的指定坐标（当前居中）
            M_Img.paste(icon, coordinate, mask=None)
        else:
            print("已经指定坐标")
            # 粘贴子图到母图的指定坐标（当前居中）
            M_Img.paste(icon, coordinate, mask=None)
    except:
        print("坐标指定出错 ")
    # 保存图片

    M_Img.save('D:\\image2\\'+serial+'-eeeeeeeeeeeeeeeeeeeee.png')

    return 'D:\\image2\\'+serial+'-eeeeeeeeeeeeeeeeeeeee.png'

def Picture_Synthesis2(son_img,
                      coordinate=None):
    """
    :param mother_img: 母图
    :param son_img: 子图
    :param save_img: 保存图片名
    :param coordinate: 子图在母图的坐标
    :return:
    """

    S_Img = Image.fromarray(son_img)

    height,width = S_Img.size
    print('width=',width,'  height=',height)
    width = width+200
    height = height+200
    mother_img= np.ones((width, height, 3), dtype=np.uint8)

    mother_img[:, :, 0] = 255  # 蓝色通道
    mother_img[:, :, 1] = 255    # 绿色通道
    mother_img[:, :, 2] = 255    # 红色通道

    cv2.imwrite('D:\\image2\\wwwwwwwww.png', mother_img, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])

    #将图片赋值,方便后面的代码调用
    M_Img = Image.open('D:\\image2\\wwwwwwwww.png')

    factor = 1#子图缩小的倍数1代表不变，2就代表原来的一半

    #给图片指定色彩显示格式
    M_Img = M_Img.convert("RGBA")  # CMYK/RGBA 转换颜色格式（CMYK用于打印机的色彩，RGBA用于显示器的色彩）

    # 获取图片的尺寸
    M_Img_w, M_Img_h = M_Img.size  # 获取被放图片的大小（母图）
    #print("母图尺寸：",M_Img.size)
    S_Img_w, S_Img_h = S_Img.size  # 获取小图的大小（子图）
    #print("子图尺寸：",S_Img.size)

    size_w = int(S_Img_w / factor)
    size_h = int(S_Img_h / factor)

    # 防止子图尺寸大于母图
    if S_Img_w > size_w:
        S_Img_w = size_w
    if S_Img_h > size_h:
        S_Img_h = size_h

    # # 重新设置子图的尺寸
    # icon = S_Img.resize((S_Img_w, S_Img_h), Image.ANTIALIAS)
    icon = S_Img.resize((S_Img_w, S_Img_h), Image.Resampling.LANCZOS)
    w = int((M_Img_w - S_Img_w) / 2)
    h = int((M_Img_h - S_Img_h) / 2)

    try:
        if coordinate==None or coordinate=="":
            coordinate=(w, h)
            # 粘贴子图到母图的指定坐标（当前居中）
            M_Img.paste(icon, coordinate, mask=None)
        else:
            print("已经指定坐标")
            # 粘贴子图到母图的指定坐标（当前居中）
            M_Img.paste(icon, coordinate, mask=None)
    except:
        print("坐标指定出错 ")
    # 保存图片

    return M_Img

def qqq(d,path,serial,rect,isphone=None):

    screenshot = d.screenshot(format='opencv')
    print(path+serial+'-testscreenshotold.png')
    cv2.imwrite(path+serial+'-testscreenshotold.png', screenshot, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])
    x,y,w,h=DrawRectWithText(screenshot,rect)

    # 切片裁剪图像
    cropped_image = screenshot[y:y+h, x:x+w]
    cv2.imwrite(path+serial+'-testscreenshot.png', cropped_image, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])

    if(isphone!=None and isphone==0):
        cropped_image = screenshot[y+50:y+120, x:x+w]
        cv2.imwrite(path+serial+'-testscreenshot2.png', cropped_image, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])
    else:
        # 切片裁剪图像
        cropped_image = screenshot[y+100:y+205, x:x+w]
        cv2.imwrite(path+serial+'-testscreenshot2.png', cropped_image, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])

def saveimg(d,rect):
    path='D:\\image2\\'

    device_info = d.device_info
    serial = device_info.get('serial')

    if(rect!=[0.03,0.10,0.94,0.4]):
        qqq(d,path,serial,rect,0)
    else:
        qqq(d,path,serial,rect)

    new_path=Picture_Synthesis(path+serial+'-testscreenshot2.png',serial)

    image=Image.open(new_path)

    # 设置目标图像大小
    target_width = 2*image.width  # 假设提升为原始宽度的两倍
    target_height =2*image.height  # 假设提升为原始高度的两倍
    target_size = (target_width, target_height)
    # 使用双线性插值进行图像分辨率提升
    upscaled_image = image.resize(target_size, 3)
    image_np = np.array(upscaled_image)
    # 转换为灰度图像
    gray_image = cv2.cvtColor(image_np, cv2.COLOR_BGR2BGRA)
    # 应用高斯模糊来进行抗锯齿处理
    blurred_image = cv2.GaussianBlur(gray_image, (3, 3), 0)
    # 图像增强（锐化）来提高清晰度
    kernel = np.array([[-1, -1, -1], [-1, 9, -1], [-1, -1, -1]])  # 定义锐化核
    image_np = cv2.filter2D(blurred_image, -1, kernel)

    # 识别文字，并指定语言
    s = pytesseract.image_to_string(image_np, lang='chi_sim')
    print('string=',s)
    text=s
    if text!=None:
        extracted_text = re.sub(r'[^\w\s]', '', text)
        extracted_text =extracted_text.rstrip("\n")
        if extracted_text != None:
            cleaned_text = extracted_text.replace(" ", "").replace('\n', '').replace('\r', '')
            #print("提取的文字：", cleaned_text)
            directory = path
            # 检查目录是否存在
            if not os.path.exists(directory):
                # 如果目录不存在，则新建目录
                os.makedirs(directory)
                #print(f"目录 '{directory}' 不存在，已创建成功")

            source_file = path+serial+'-testscreenshot.png'
            target_directory = directory+'\\'

            # 确保目标目录存在
            os.makedirs(target_directory, exist_ok=True)

            files = os.listdir(directory)

            # 统计文件数量
            file_count = len(files)

            new_file_name = cleaned_text+str(file_count-1)+".png"

            # 执行文件复制操作
            shutil.copy(source_file, target_directory+new_file_name)

            return target_directory,new_file_name,cleaned_text

        else:
            print("未找到匹配的内容")
    else:
        print("未找到匹配的内容")

    '''
    template = cv2.imread(path+'re.png', 0)
    x,y=isimg(d,template)
    if(x!=None):
        d.click(x,y)
    '''

def chinese_text_to_hash(text):
    # 将中文文本转换为 utf-8 编码
    encoded_text = text.encode('utf-8')

    # 使用 hashlib 中的 sha256 哈希算法进行哈希处理
    sha256_hash = hashlib.sha256(encoded_text).hexdigest()

    return sha256_hash

def calculate_relative_position(x, y,image_width,image_height):
    relative_x = x / image_width
    relative_y = y / image_height
    return relative_x, relative_y

def remove_suffix(text, suffix):
    if text.endswith(suffix):
        return text[:-len(suffix)]
    return text

def convert_coordinates(bbox, image_width, image_height):
    """将边界框坐标转换为 Yolo 坐标

    Args:
        bbox: 边界框的坐标，格式为 (xmin, ymin, xmax, ymax)
        img_width: 图像的宽度（像素数）
        img_height: 图像的高度（像素数）
        grid_num: 网格数量（整数）

    Returns:
        一个包含 5 个值的元组，分别为目标类别、中心点 x 坐标、中心点 y 坐标、宽度、高度，
        其中中心点坐标、宽度和高度都是相对于图像尺寸的 Yolo 坐标。
    """
    #print('bbox=',bbox)
    #print('w h =',image_width,image_height)
    x_min, y_min, x_max, y_max = bbox

    x_center = (x_min + x_max) / 2
    y_center = (y_min + y_max) / 2

    # Calculate width and height of the bounding box
    box_width = x_max - x_min
    box_height = y_max - y_min

    # Normalize to [0, 1] range
    x_center_norm = x_center / image_width
    y_center_norm = y_center / image_height
    box_width_norm = box_width / image_width
    box_height_norm = box_height / image_height

    return x_center_norm, y_center_norm, box_width_norm, box_height_norm

def plot_square(center_x, center_y,path_to_your_image,imagename,name,side_length=330):

    path='D:\\image2\\'

    #print('path_to_your_image=',path_to_your_image)
    print('imagename=',imagename)
    #print('center_x=',center_x,'center_y=',center_y)

    image_pil = Image.open(path_to_your_image+imagename)
    image_np = np.array(image_pil)

    # 将NumPy数组传递给OpenCV的cv2.imread函数
    image = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)

    # 计算正方形的四个顶点坐标
    top_left = int(center_x - side_length / 2), int(center_y - side_length / 2)
    bottom_right = int(center_x + side_length / 2), int(center_y + side_length / 2)

    h,w, channels =image.shape

    # 计算每个顶点的相对位置
    relative_x1, relative_y1,relative_x2, relative_y2 = convert_coordinates((top_left[0],top_left[1],bottom_right[0],bottom_right[1]),w,h)

    suffix = ".png"

    result = remove_suffix(imagename, suffix)

    total_lines=0

    try:
        with open(path+'classes.txt', 'a', encoding='utf-8') as file:
            total_lines=write_and_check_duplicate(path+'classes.txt',name+'\n')
    except FileNotFoundError:
        # 如果文件不存在，则创建并写入内容
        with open(path+'classes.txt', 'w', encoding='utf-8') as file:
            total_lines=write_and_check_duplicate(path+'classes.txt',name+'\n')

    try:
        with open(path+result+'.txt', 'a', encoding='utf-8') as file:
            file.write(str(total_lines)+' '+str(relative_x1)+' '+ str(relative_y1)+' '+str(relative_x2)+' '+ str(relative_y2)+'\n')
    except FileNotFoundError:
        # 如果文件不存在，则创建并写入内容
        with open(path+result+'.txt', 'w', encoding='utf-8') as file:
            file.write(str(total_lines)+' '+str(relative_x1)+' '+ str(relative_y1)+' '+str(relative_x2)+' '+ str(relative_y2)+'\n')


    #print("顶点1相对位置：({:.2f}, {:.2f})".format(relative_x1, relative_y1))
    #print("顶点2相对位置：({:.2f}, {:.2f})".format(relative_x2, relative_y2))

    '''
    # 画出正方形
    cv2.rectangle(image, top_left, bottom_right, (0, 255, 0), 2)

    # 显示图片
    cv2.imshow('Square', image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    '''

def plot_square2(center_x, path_to_your_image,imagename,name):

    path='D:\\image2\\'

    #print('path_to_your_image=',path_to_your_image)
    #print('imagename=',imagename)

    image_pil = Image.open(path_to_your_image+imagename)
    image_np = np.array(image_pil)

    # 将NumPy数组传递给OpenCV的cv2.imread函数
    image = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)

    # 计算正方形的四个顶点坐标
    top_left = int(center_x - 180 / 2), int(500 - 550 / 2)
    bottom_right = int(center_x + 180 / 2), int(500 + 550 / 2)

    h,w, channels =image.shape

    # 计算每个顶点的相对位置
    relative_x1, relative_y1,relative_x2, relative_y2 = convert_coordinates((top_left[0],top_left[1],bottom_right[0],bottom_right[1]),w,h)

    suffix = ".png"

    result = remove_suffix(imagename, suffix)

    total_lines=0

    try:
        with open(path+'classes.txt', 'a', encoding='utf-8') as file:
            total_lines=write_and_check_duplicate(path+'classes.txt',name+'\n')
    except FileNotFoundError:
        # 如果文件不存在，则创建并写入内容
        with open(path+'classes.txt', 'w', encoding='utf-8') as file:
            total_lines=write_and_check_duplicate(path+'classes.txt',name+'\n')

    try:
        with open(path+result+'.txt', 'a', encoding='utf-8') as file:
            file.write(str(total_lines)+' '+str(relative_x1)+' '+ str(relative_y1)+' '+str(relative_x2)+' '+ str(relative_y2)+'\n')
    except FileNotFoundError:
        # 如果文件不存在，则创建并写入内容
        with open(path+result+'.txt', 'w', encoding='utf-8') as file:
            file.write(str(total_lines)+' '+str(relative_x1)+' '+ str(relative_y1)+' '+str(relative_x2)+' '+ str(relative_y2)+'\n')


    #print("顶点1相对位置：({:.2f}, {:.2f})".format(relative_x1, relative_y1))
    #print("顶点2相对位置：({:.2f}, {:.2f})".format(relative_x2, relative_y2))

def write_and_check_duplicate(filename, text):
    # 打开文件以读取内容
    with open(filename, 'r', encoding='utf-8') as file:
        lines = file.readlines()

    line_number = 0
    total=0
    # 判断是否存在相同的文字并记录行数
    for i, line in enumerate(lines):
        total+=1
        if text in line:
            line_number = i

    # 如果存在相同的文字，则输出文字所在行数
    if line_number!=0:
        print(f"文件中已经存在相同内容，位于第 {line_number} 行。")
    else:
        line_number=total
        # 打开文件以追加内容
        with open(filename, 'a', encoding='utf-8') as file:
            # 写入新的文字并换行
            file.write(text)
        #print("内容已写入文件。")
        #print(f"文件 '{filename}' 总共有 {line_number} 行。")

    return line_number


if __name__ == "__main__":
    print('')

    device='emulator-5554'
    d = u2.connect(device)
    device_info = d.device_info
    serial = device_info.get('serial')
    qqq(d,'D:\\image2\\',serial,[0.02,0.12,0.96,0.5],0)
    '''
    screenshot =d.screenshot(format='opencv')
    img = cv2.cvtColor(screenshot, cv2.COLOR_BGR2GRAY)
    h,w=img.shape
    path='D:\\image2\\'
    imagecv(w,d,path+device,[0.03,0.10,0.94,0.4])
    #saveimg(d)
    '''
    #plot_square(508, 755,'D:\\image2\\','普洱生茶饼20.png','普洱生茶饼')
